package io.github.hellomaker.domain.strategy.service.armory;

import io.github.hellomaker.domain.strategy.adapter.repository.IStrategyRepository;
import io.github.hellomaker.domain.strategy.model.entity.StrategyAwardEntity;
import io.github.hellomaker.domain.strategy.model.entity.StrategyEntity;
import io.github.hellomaker.domain.strategy.model.entity.StrategyRuleEntity;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.security.SecureRandom;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class StrategyArmoryDispatch implements IStrategyArmory, IStrategyDispatch{

    @Resource
    IStrategyRepository strategyRepository;

    @Override
    public boolean assembleLotteryStrategy(Long strategyId) {
        List<StrategyAwardEntity> strategyAwardEntities = strategyRepository.queryStrategyAwardList(strategyId);

        //装配全部普通策略概率
        assembleLotteryStrategy(String.valueOf(strategyId), strategyAwardEntities);


        StrategyEntity strategyEntity = strategyRepository.queryStrategyEntity(strategyId);
        String ruleWeight = strategyEntity.getRuleWeight();
        if (ruleWeight == null) {
            return true;
        }
        StrategyRuleEntity strategyRuleEntity = strategyRepository.queryStrategyRuleEntity(strategyId, ruleWeight);
        Map<Integer, List<Integer>> ruleWeightValues = strategyRuleEntity.getRuleWeightValues();
        Set<Integer> weights = ruleWeightValues.keySet();
        for (Integer weight : weights) {
            List<Integer> awardIdList = ruleWeightValues.get(weight);
            List<StrategyAwardEntity> ruleAwardList = strategyAwardEntities.stream().filter(e ->
                    awardIdList.contains(e.getAwardId())
                    ).collect(Collectors.toList());
            assembleLotteryStrategy(String.valueOf(strategyId).concat("_").concat(String.valueOf(weight)), ruleAwardList);
        }

        return true;
    }

    @Override
    public boolean assembleLotteryStrategy(String key, List<StrategyAwardEntity> strategyAwardEntities) {
        BigDecimal minRate = strategyAwardEntities.stream().map(StrategyAwardEntity::getAwardRate).min(BigDecimal::compareTo).orElse(BigDecimal.ZERO);

        BigDecimal totalRate = strategyAwardEntities.stream().map(StrategyAwardEntity::getAwardRate).reduce(BigDecimal.ZERO, BigDecimal::add);

        // 4. 用 1 % 0.0001 获得概率范围，百分位、千分位、万分位
//        BigDecimal rateRange = totalRate.divide(minRate, 0, RoundingMode.CEILING);

        int rateRange = 0;
        int startRange = 0;
        Map<Integer, Integer> keyMap = new HashMap<>();
        for (StrategyAwardEntity strategyAwardEntity : strategyAwardEntities) {
            BigDecimal awardRate = strategyAwardEntity.getAwardRate();
            int singleRange = awardRate.multiply(new BigDecimal(10000)).intValue();
            for (int i = 0; i < singleRange; i++, startRange++) {
                keyMap.put(startRange, strategyAwardEntity.getAwardId());
            }
            rateRange += singleRange;
        }
        strategyRepository.storeStrategyAwardSearchRateTable(key, rateRange, keyMap);
        return true;
    }


    @Override
    public Integer getRandomAwardId(Long strategyId) {
        int rateRange = strategyRepository.getRateRange(strategyId);
        Random random = new SecureRandom();
        int randomKey = random.nextInt(rateRange);
        return strategyRepository.getStrategyAwardAssemble(strategyId, randomKey);
    }

    @Override
    public Integer getRandomAwardId(Long strategyId, Integer ruleWeight) {
        int rateRange = strategyRepository.getRateRange(strategyId, ruleWeight);
        Random random = new SecureRandom();
        int randomKey = random.nextInt(rateRange);
        return strategyRepository.getStrategyAwardAssemble(strategyId, ruleWeight, randomKey);
    }


}
